/**
 * @file	watchdog.c
 * @author	chipsea
 * @brief	
 * @version	0.1
 * @date	2020-11-30
 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd.
 * @note
 */
#include "rom_sym_def.h"
#include "watchdog.h"
#include "error.h"
#include "pwrmgr.h"
#include "clock.h"
#include "jump_function.h"
#include	"watchdog.h"


extern volatile uint8 g_clk32K_config;
extern uint32_t s_config_swClk1;

typedef struct {
	bool    		enable;
	WdtRspMode_t	mode;
	pfnHdlCB_t 		handleCB;
}WdtCtl_t;

WdtCtl_t wdtCtl;


/**
* @fn static void __attribute__((used)) hal_WATCHDOG_IRQHandler(void)
* @brief WDT interrupt handler funtion. wdt clock source is 32KHz low speed clock.
* @param[in] none
* @return none.
*/
void __attribute__((used))  hal_WATCHDOG_IRQHandler(void)
{
//	volatile uint32_t a;
//	a = AP_WDT->EOI;
//	AP_WDT->CRR = 0x76;
	if(wdtCtl.handleCB) {
		wdtCtl.handleCB();
	}
}


/**
* @fn void HalWdtFeed(void)
* @brief wdt feed
* @param[in] none
* @return none.
*/
void HalWdtFeed(void)
{
	AP_WDT->CRR = 0x76;
}


/**
* @fn static bool watchdog_init(WDG_CYCLE_Type_e cycle)
* @brief wdt initialize config
* @param[in] cycle: WDG_CYCLE_Type_e 
* @return boot SUCCESS/.
*/

static bool watchdog_init(void)
{
    volatile uint32_t a;
    uint8_t delay;

    if(g_clk32K_config == CLK_32K_XTAL)//rtc use 32K XOSC,watchdog use the same
    {
        AP_PCRM->CLKSEL |= (1UL<<16);
    }
    else
    {
        AP_PCRM->CLKSEL &= ~(1UL<<16); //rtc use 32K RCOSC,watchdog use the same
    }

    hal_clk_gate_enable(MOD_WDT);
    s_config_swClk1|=_CLK_WDT; //add watchdog clk in pwrmg wakeup restore clk;

    if((AP_PCR->SW_RESET0 & 0x04)==0)
    {
        AP_PCR->SW_RESET0 |= 0x04;
        delay = 20;

        while(delay-->0);
    }

    if((AP_PCR->SW_RESET2 & 0x04)==0)
    {
        AP_PCR->SW_RESET2 |= 0x04;
        delay=20;

        while(delay-->0);
    }

    AP_PCR->SW_RESET2 &= ~0x20;
    delay=20;

    while(delay-->0);

    AP_PCR->SW_RESET2 |= 0x20;
    delay=20;

    while(delay-->0);

    a = AP_WDT->EOI;
    AP_WDT->TORR = HAL_WDG_CFG_CYCLE;       //config wdt cycle
    
	if(wdtCtl.mode == WDG_USE_INT_MODE)
	{
		 JUMP_FUNCTION(V10_IRQ_HANDLER)                  =   (uint32_t)&hal_WATCHDOG_IRQHandler;
		AP_WDT->CR = 0x1F;								//use intteruct mode
		NVIC_SetPriority((IRQn_Type)WDT_IRQn, IRQ_PRIO_HAL);
		NVIC_EnableIRQ((IRQn_Type)WDT_IRQn);
	}	
	else if(wdtCtl.mode == WDG_USE_POLLING_MODE)
	{
		JUMP_FUNCTION(V10_IRQ_HANDLER)                  =   0;	
		AP_WDT->CR = 0x1D;								//no use intteruct mode
		NVIC_DisableIRQ((IRQn_Type)WDT_IRQn);
	} 
	
    AP_WDT->CRR = 0x76;
    
    return SUCCESS;
}

/**
* @fn void HalWdtInit(FunctionalState_t newState, WdtRspMode_t mode, pfnHdlCB_t irqHdlCallback)
* @brief wdt initialize
* @param[in] newState: ENABLE or DISABLE
* @param[in] mode: WDT_RSP_MODE_NO_INT or WDT_RSP_MODE_INT
* @param[in] irqHdlCallback: interrupt handle callback
* @return none.
*/
void  HalWdtInit(FunctionalState_t newState, WdtRspMode_t mode,pfnHdlCB_t irqHdlCallback)
{

	wdtCtl.mode = mode;
	wdtCtl.handleCB = irqHdlCallback;
	if(newState == ENABLE) {
		watchdog_init();
        JUMP_FUNCTION(HAL_WATCHDOG_INIT) = (uint32_t)&watchdog_init;
	}
	else{
		JUMP_FUNCTION(HAL_WATCHDOG_INIT) = NULL;
	}

}


